﻿package domino

{
  import adobe.utils.CustomActions;
  import Box2D.Collision.Shapes.b2PolygonDef;
  import Box2D.Collision.Shapes.b2PolygonShape;
  import Box2D.Collision.Shapes.b2Shape;
  import Box2D.Common.Math.b2Vec2;
  import Box2D.Dynamics.b2Body;
  import Box2D.Dynamics.b2World;
  import flash.display.Graphics;
  import flash.display.Sprite;

  import flash.display.DisplayObject;
  import flash.events.EventDispatcher;
  import flash.geom.Point;
  import flash.geom.Vector3D;
  import Box2D.Dynamics.*;
  import Box2D.Collision.*;
  //import flash.geom
  
  
  

  
public class actor extends EventDispatcher
{
	 public var _body:b2Body;
     public var _costume:DisplayObject;
     public var pointImpulse:Point;
	 public var angle:int = 0;
	 public var alpha2:Number = 0;
	 public var selectable:Boolean = false;
	 public var diagonal:Number = 0;
     public var alpha10:Number = 0;
	 public var alpha:Number = 0;
	 public var select:Boolean = false;
	 
	
  public function actor(body:b2Body,costume:DisplayObject){

   _body = body;
   _body.SetUserData(this);
  
   _costume = costume;
   
    diagonal = Math.sqrt(_costume.width * _costume.width + _costume.height * _costume.height);
	select = false;
	
	//trace(diagonal+" diagonal")
    alpha10=Vector3D.angleBetween(new Vector3D(0,-1,0),new Vector3D(_costume.width,-_costume.height,0));
	    // trace(alpha10 * 180 / Math.PI + " alpha10")
		 	 
  }//end
  
 
 
  public function update():void {
	  updateBody();
	  updateOther();
	}//end
//////////////////////////////////////////////////	
  private function updateOther():void{
	 if ((_costume.x > 800) || (_costume.y >600)||(_costume.x < -200) || (_costume.y <-200)){
	  dispatchEvent(new OutOfScreen(OutOfScreen.OUT_DOMIN));
	  trace(this + " should be remove");
	 }
  }//end

  public function rotate(angl:int):void {
	  angle -= angl;
	 // var a = 2 * Math.PI / (angle % 18) ;
	  //trace(angle);
  
	  _body.SetXForm(new b2Vec2(_body.GetPosition().x, _body.GetPosition().y), angle*Math.PI/180);
	  _costume.rotation=angle;
	  }
	///////////////////////////////////////////////  
  private function updateBody():void {
	//  if (this.select == true)
	  // return;
	 //trace((_body.GetAngle() -alpha) + "_body.GetAngle()-this.alpha");
    if(this is actorTriangle){//||(this is actorTrident)){
	_costume.x = _body.GetPosition().x * 30;
    _costume.y = _body.GetPosition().y * 30;	
    // trace(_costume.width+" costume" + _costume.height);
    _costume.rotation = _body.GetAngle() * 180 / Math.PI;
	return ;
	}
	/*if(this is actorTrident){
	_costume.x = _body.GetPosition().x * 30 - _costume.width/2;
    _costume.y = _body.GetPosition().y * 30 - _costume.height;	
    // trace(_costume.width+" costume" + _costume.height);
    _costume.rotation = _body.GetAngle() * 180 / Math.PI;
	}*/
	if (this is actorCircle) {
	//	diagonal = _costume.width;
	  /* _costume.x = _body.GetPosition().x * 30 - this.diagonal / 2 ;
       _costume.y = _body.GetPosition().y * 30 - this.diagonal / 2 ;	
       _costume.rotation = _body.GetAngle() * 180 / Math.PI;*/
		//return;
		}
	{
	_costume.x = _body.GetPosition().x * 30 + this.diagonal / 2 * Math.sin(_body.GetAngle()-alpha10);
    _costume.y = _body.GetPosition().y * 30 - this.diagonal / 2 * Math.cos(_body.GetAngle()-alpha10);	
    // trace(_costume.width+" costume" + _costume.height);
    _costume.rotation = _body.GetAngle() * 180 / Math.PI;
	return;
	}


  }//end

  public function getActorPosition():b2Vec2 {
	  var position:b2Vec2 = new b2Vec2(actor(this)._body.GetPosition().x, this._body.GetPosition().y);
	  return position;
	  }//end

 public function removeActor(_world:b2World):void {
	   //remove sprite
	   if(_body.GetShapeList().GetUserData() is b2Body)
	    _world.DestroyBody(_body.GetShapeList().GetUserData());
	   
	   _world.DestroyBody(_body);
	   
	   //remove b2Body
	   
	   if (this is actorCoin)
	    actorCoin(this).removeLine(_costume.parent);
	   if (this is actorCross){
	       if(actorCross(this).Arrow)
		    actorCross(this).removeArrow(_costume.parent);
	   }
	 
	    if (this is actorTrident){
	       if(actorTrident(this).Arrow)
		    actorTrident(this).removeArrow(_costume.parent);
	   }
	 
	    if (this is actorTrident2){
	       if(actorTrident2(this).Arrow)
		    actorTrident2(this).removeArrow(_costume.parent);
	   }
	   
	    if (this is actorPendulum){
	       if(actorPendulum(this).Arrow)
		    actorPendulum(this).removeArrow(_costume.parent);
	   }
	    if (this is actorPendulum2){
	       if(actorPendulum2(this).Arrow)
		    actorPendulum2(this).removeArrow(_costume.parent);
	   }
	   
	   
	   // _costume.removeChild(
	   if(_costume is Sprite)
	   _costume.parent.removeChild(_costume);
	  // trace("up1");
	   
	  }//end
public function markAsSelectable():Boolean {
		 var pos:b2Vec2 = getActorPosition();
	//	 trace(pos.x*30 + " pos " + pos.y*30);
		 if ((pos.x * 30 > 552) && (pos.x * 30 < 640) && (pos.y * 30 > 0) && (pos.y * 30 < 480)) {
		   selectable = true;	 
		   return selectable;
		 }
		 else{ 
		     selectable = false;	 
			 return selectable;	 
		 }
		 
		  }//end
	  
public function CheckIntersection(box:actor, start:b2Vec2, end:b2Vec2, mouse:b2Vec2):Array {
	
	if ((box is actorDomino) || (box is actorTriangle)) {
		//trace(box._body.GetPosition().x*30 + " coord " + box._body.GetPosition().y*30);
	
	    var arr:Array = [];
		var normal:b2Vec2 = new b2Vec2();
		var segment:b2Segment = new b2Segment();
		var segment2:b2Segment = new b2Segment();
		
		var lambda:Array = [1];
		segment.p1 = start;
		segment.p2 = end;
		
	    var hit:Boolean = 	box._body.GetShapeList().TestSegment(box._body.GetXForm(), lambda, normal, segment, 1);
		if(hit){
	//	 trace(hit + "hit");
		 var entryPoint:b2Vec2 = segment.p1.Copy();
		 entryPoint.Multiply(1 - lambda[0]);
		 var tmp:b2Vec2 = segment.p2.Copy();
		 tmp.Multiply(lambda[0]);
		 entryPoint.Add(tmp);
	     var start_mouse:Number =Point.distance(new Point(entryPoint.x, entryPoint.y), new Point(mouse.x, mouse.y));	 
	     arr.push(entryPoint);
	     arr.push(start_mouse);
		} 
		else{
		     arr.push(null);
	         arr.push(null);	 
			}
		 
		segment2.p1 = segment.p2;
		segment2.p2 = segment.p1
		
	    hit = 	box._body.GetShapeList().TestSegment(box._body.GetXForm(), lambda, normal, segment2, 1);
		
		if(hit){
		// trace(hit + "hit");
		 var exitPoint:b2Vec2 = segment2.p1.Copy();
		 exitPoint.Multiply(1 - lambda[0]);
		 tmp = segment2.p2.Copy();
		 tmp.Multiply(lambda[0]);
		 exitPoint.Add(tmp);	
		 var exit_mouse:Number =Point.distance(new Point(exitPoint.x, exitPoint.y), new Point(mouse.x, mouse.y));
		 arr.push(exitPoint);
	     arr.push(exit_mouse);	 
	      }
		else {
			 arr.push(null);
	         arr.push(null);
			}	 

	return arr;
	
	 }
	 else return null ;
	
	}//end
	public function boxToTriangle():void {
		
		var shape:b2Shape = this._body.GetShapeList();
		//trace(shape);
		var polShape:b2PolygonShape = b2PolygonShape(shape);
		//polShape.
		 var count:int = polShape.GetVertexCount();
          var normals:Array=polShape.GetNormals();
		 // trace(normals[0]+ " normal");
		  var verts:Array = new Array();
		  var newVerts:Array = new Array();
		  
          verts = polShape.GetVertices();
		  var i:int;
          for( i = 0; i < count; i++ )
          {
               //verts[i].x = 4;
			  newVerts.push(this._body.GetWorldPoint( verts[i] ));
		  // trace(newVerts[i].x + " newvert " +newVerts[i].y);
		   //trace(verts[i].x + " vert " +verts[i].y);
		   
		  }	
		  
			
			
	}//end

///////////////////////////////////////
	  public function GetArrowAngle(_pointImpulse:Point,_pointCenter:Point,rotation:Number):Number {
		 //trace("1");
		  var i:int=0;
		  var Vector1:Vector3D = new Vector3D(0,-1,0);
	     // var shape:b2Shape; 
		  var Vector2:Vector3D = new Vector3D(_pointImpulse.x -_pointCenter.x,_pointImpulse.y -_pointCenter.y,0);
	    //  var alpha:Number;
		  var beta:Number = Vector3D.angleBetween(Vector1, Vector2);
		//  trace(beta + " =beta");
		 /* alpha2 = rotation;
		//  trace(beta*180/Math.PI+ " beta");
		  var shapes:Array = [];	
		  var currentPoint:b2Vec2= new b2Vec2(_pointImpulse.x/30,_pointImpulse.y/30);
	      Vector1.normalize();
		  Vector2.normalize();
		 //trace("2");
		 alpha = Math.acos((Vector1.x * Vector2.x + Vector1.y * Vector2.y) / Math.sqrt(( Vector1.x * Vector1.x + Vector1.y * Vector1.y) * (Vector2.x * Vector2.x + Vector2.y * Vector2.y)) );
		 alpha2 = alpha;
		 var index:int = -1;
		 
		 if(this is actorDomino){
			 index = actorDomino(this).shapeIndex;
		    
			 
		 if (index == 3 ) {
			 return Math.PI + rotation* Math.PI/180;
			 }
		 if (index == 1 ) {
			 return 0+ rotation* Math.PI/180 ;
			 }
		 if (index == 0 ) {
			 return  3*Math.PI/2 + rotation* Math.PI/180;
			 }
		 if (index == 2 ) {
			 return Math.PI/2+rotation* Math.PI/180;
			 }
			 
		 }*/
	//	trace(index);
		if(Vector1>Vector2)
		   return -beta;
		  else
		   return beta;
		  
		 }//end
	  
	
	    
 
 public function move(x:int,y:int):void { 
	  _body.SetXForm(new b2Vec2(_body.GetPosition().x+x/30, _body.GetPosition().y+y/30), _body.GetAngle());
	  _costume.x +=x ;
	  _costume.y +=y ;
	 }//end
  
  
 public function moveDomino(_pointImpulse:b2Vec2,_pointCenter:b2Vec2,figureAngle:Number,arrowAngle:Number,_k:Number):Boolean {
	    
	   var impulse:b2Vec2;
	   var x2:Number;
	   var y2:Number;
	   var force:Number = 2.5;
	   if (this is domino.actorCircle)
	    force = 4;
		
	    x2 =this._body.GetMass()*force* Math.sin(arrowAngle*Math.PI/180);
	    y2 =-this._body.GetMass()*force* Math.cos(arrowAngle*Math.PI/180);
	
	     impulse = new b2Vec2(x2,y2);
		_body.ApplyImpulse(impulse,_pointImpulse);
	   return true;
  }//end
   public function moveCircle(_pointImpulse:Point):void {
	    
	   var impulse:b2Vec2;
	   var pointImpulse:b2Vec2;
	   
	   var length:int;
	   var angle:int;
	    
	   pointImpulse = new b2Vec2(_pointImpulse.x / 30, _pointImpulse.y / 30);
	  // length = Point.distance(_pointImpulse, new Point(_body.GetPosition().x * 30, _body.GetPosition().y * 30));  		
       
		//trace("angle is "+Vector3D.angleBetween(normalVector, Vector2)); 
	    //trace("lenght is "+length/30); 
		
		if(pointImpulse.x>_body.GetPosition().x)	
	      impulse = new b2Vec2(-length/3, 0);
		else
		  impulse= new b2Vec2(length/3, 0);

		_body.ApplyImpulse(impulse,pointImpulse);
	}//end

 }

}
